home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BMUG Revelations
/
BMUG Revelations.toast
/
Utilities
/
Random
/
Commodore 64c
/
SOURCE
/
Processor.c
< prev
next >
Wrap
Text File
|
1994-03-19
|
5KB
|
213 lines
/*
Commodore 64 Emulator v0.1 Earle F. Philhower III
Copyright (C) 1993-4 (st916w9r@dunx1.ocs.drexel.edu)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Vectors.h"
#include "Flags.h"
#include "Registers.h"
#include "Memory.h"
#include "Modes.h"
#include "Stack.h"
#include "Keyboard.h"
#include <AppleEvents.h>
extern WindowPtr VICWind;
extern Cursor commie;
extern void (* instruct[256]) ();
extern byte cycletime[256];
extern int missingROM;
#define kWindowStrings 500
enum { kRunningWindow=1, kSuspendedWindow };
byte interruptProcessor;
static byte numLeftSameChar;
static void ProcessPerLine(void);
extern void ProcessorLoop(void);
void ProcessorLoop()
{
int scanLines, vicCalls;
byte instructCode, oldMemoryMap, processorCycles, col;
byte *dc01, *dc00, *d012, *d011, *d018;
Str255 str;
unsigned long tempa1, tempa2, tempd1, tempd2;
byte **localMemory;
/* Set up window, cursor for running state */
GetIndString(str, kWindowStrings, kRunningWindow);
SetWTitle(VICWind, str);
SetCursor(&commie);
ObscureCursor();
/* Initialize precomputed addresses (minimal speed gain) */
dc00=&RAM[0xdc00];
dc01=&RAM[0xdc01];
d012=&RAM[0xd012];
d011=&RAM[0xd011];
d018=&RAM[0xd018];
/* Set up the memory dereferences, and store current map */
oldMemoryMap=*RAMp1;
SetUpMemoryMap();
/* Some flags and counters necessray to be initialized */
interruptProcessor=0;
numLeftSameChar=0;
processorCycles=0;
scanLines=0;
vicCalls=0;
while (interruptProcessor==0) {
tempd2=pc;
asm {
move.l a1, tempa1
move.l d1, tempd1
move.l tempd2, d1
move.l memory, a1
lsl.l #2, d1
move.l (a1, d1.l), a1
move.b (a1), instructCode
move.l tempd1, d1
move.l tempa1, a1
};
/*instructCode = ImmediateByte();*/ pc++;
processorCycles += cycletime[instructCode];
(*instruct[instructCode])();
/* Set up the memory map if it has changed */
if (*RAMp1!=oldMemoryMap) {
SetUpMemoryMap();
oldMemoryMap=*RAMp1; }
/* If we've done 35 cycles, we've gone through 1 scanline */
if (processorCycles>35) {
processorCycles=0;
/* Update the current VIC scan register */
if (++*d012==0) *d011 ^= 128;
*d018 |=1;
/* If we've gone through 350 lines, we've due for an interrupt */
if (++scanLines>350) {
scanLines=0;
/* Set raster to 0 line */
*d012=0;
*d011&=127;
/* Currently we just update the keyboard registers */
ProcessPerLine();
if (++vicCalls==2) {
RedrawVIC();
vicCalls=0; }
/* Call interrupt routine if interrupts enabled */
if ((flags&INT)==0) {
PushWord(pc);
Push(flags);
pc=WordAt(IrqTo);
}
}
}
/* Set up the keyboard register according to precomputed values */
*dc01=scanCode[*dc00];
}
/* Done processing, reset window, cursor */
RedrawVIC();
SetCursor(&qd.arrow);
GetIndString(str, kWindowStrings, kSuspendedWindow);
SetWTitle(VICWind, str);
}
/* Called once per scanline, currently check for keypress or mouse button */
static void ProcessPerLine()
{
EventRecord evt;
int x;
char theChar;
/* We keep the same keyboard map for 1/30th of a second */
if (numLeftSameChar==0) {
numLeftSameChar=2;
/* Check for any key or mouse press */
if (GetNextEvent(-1, &evt)!=false)
switch(evt.what) {
/* A mouseclick stops our simulation */
case mouseDown: MiniHandleMouseDown(evt); break;
case updateEvt:
BeginUpdate((WindowPtr)evt.message);
EndUpdate((WindowPtr)evt.message); break;
case app4Evt:
if (evt.message&1);
else interruptProcessor=1;
break;
case kHighLevelEvent :
AEProcessAppleEvent(&evt); break;
/* A keypress is simulated by fudging the CIA registers */
case keyDown: case autoKey:
theChar = evt.message&charCodeMask;
if ((evt.modifiers&cmdKey)!=0)
DoMenuChoice(MenuKey(theChar));
else {
AppleScanKeyboard(evt.message&charCodeMask, evt.modifiers);
SetupScanCodes();}
}
/* No keypress, so clear out keyboard register fudge */
else { for (x=0; x<256; x++) scanCode[x]=0xff; SystemTask(); }
}
else numLeftSameChar--;
}
#define ALIGNBYTE
MiniHandleMouseDown(event)
EventRecord event;
{
WindowPtr theWind;
GrafPtr gp;
Point x;
short thePart;
extern Rect dragRect;
thePart=FindWindow(event.where, &theWind);
switch(thePart) {
case inSysWindow: SystemClick(&event, theWind); interruptProcessor=1; break;
case inDrag:
DragWindow(theWind, event.where, &dragRect);
#ifdef ALIGNBYTE
GetPort(&gp);
SetPort(theWind);
x.h=x.v=0;
LocalToGlobal(&x);
x.h&=0xfff8;
MoveWindow(theWind, x.h, x.v, TRUE);
SetPort(gp);
#endif
break;
case inMenuBar: DoMenuChoice(MenuSelect(event.where)); break;
case inContent: interruptProcessor=1; break;
}
}